home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / VANTAGE_ / DELETE_F.C < prev    next >
C/C++ Source or Header  |  1989-09-05  |  23KB  |  969 lines

  1. /**************************************************************/
  2.  
  3. /*    This is a Vantage VCMD written in LightSpeed C V3.0.
  4.     It allows a group of files in a folder to be deleted with one
  5.     command. The files to be deleted are specified by an MS-DOS
  6.     style wildcard filename and may also be filtered by file type
  7.     or creator.
  8.     Feel free to use it, abuse it, or distribute it as you see fit.
  9.  
  10.     To build the VCMD resource, set the following project types:
  11.  
  12.         Code Resource
  13.         File Type        =    VEXT
  14.         Creator            =    VEXI
  15.         Custom Header    =    ON (checked)
  16.         Type            =    VCMD
  17.         ID                =    1 (arbitrary)
  18.         Attrs            =    20
  19.         
  20.     Also include the MacTraps and strings libraries and check the
  21.     MacHeaders option in the code generation options dialog.
  22.     
  23.     
  24.                             Dave McWherter, 7/23/89
  25.                             Signature Software
  26.                             215-639-8764
  27. */
  28.     
  29.  
  30. /**************************************************************/
  31.  
  32. #include    <MacTypes.h>
  33.  
  34. /**************************************************************/
  35. /* Data type aliases:    */
  36.  
  37. #ifndef    bool
  38.     #define    bool    int
  39. #endif
  40.  
  41. #ifndef uchar
  42.     #define    uchar    unsigned char
  43. #endif
  44.  
  45. /****************************************************************/
  46. /* Status codes for Vantage:    */
  47.  
  48. #define    OK    0
  49. #define    PASTE_OK 1
  50. #define    ERR    -1
  51.  
  52. /****************************************************************/
  53. /* Vantage's SFGet dialog and its buttons (defined in Vantage):    */
  54.  
  55. #define    SFGetDlog        5
  56.  
  57. #define    OpenButton        1
  58. #define    CancelButton    3
  59. #define    ListFilesButton    11
  60.  
  61. /****************************************************************/
  62. /* Items in our setup dialog:    */
  63.  
  64. #define    OKBUTTON        1
  65. #define    CANCELBUTTON    2
  66. #define    NAMETEXT        5
  67. #define    TYPETEXT        9
  68. #define    CREATORTEXT        11
  69.  
  70. /****************************************************************/
  71. /* Misc. stuff:    */
  72.  
  73. #define    MAXLIST    5000    /* maximum size of our list of filenames or result text    */
  74.  
  75. /****************************************************************/
  76. /* Prototypes for our routines:    */
  77.  
  78.         void    header(void);
  79.         
  80.         void    main(void);
  81.         
  82. pascal    int        open(uchar *vantdata, char **errmsg);
  83.  
  84. pascal    int        close(uchar *vantdata, char **errmsg);
  85.  
  86. pascal    int        execute(uchar *oldtext, long oldlength, Handle *newtext, long *newlength,
  87.                         uchar *vantdata, Handle winddata, char **errmsg);
  88.                         
  89. pascal    int        idle(Handle menu, int mitem, uchar *vantdata, Handle winddata, char **errmsg);
  90.  
  91.         void    return_errmsg(char *msg, char **msgptr);
  92.         
  93.         void    putbyte(uchar byt);
  94.         
  95.         void    putstring(char *str);
  96.  
  97. pascal    int        SFDlogHook(int item, DialogPtr dlogptr);
  98.  
  99. pascal    bool    SFFileFilter(HFileInfo *iop);
  100.  
  101.         bool    do_param_dialog(void);
  102.         
  103.         long    Get4TextChars(DialogPtr dlogptr, int itemnum);
  104.         
  105.         void    Set4TextChars(DialogPtr dlogptr, long itemval, int itemnum);
  106.  
  107.         bool    match_file(HFileInfo *ioparms);
  108.         
  109.         bool    match_name(char *name);
  110.         
  111.         char    tolower(char c);
  112.  
  113.         char    *strcpy(char *s1, char *s2);
  114.  
  115. /****************************************************************/
  116. /* Our custom code header used by Vantage to call the VCMD.
  117.  
  118.     Several things to note here:
  119.  
  120.     1.) Be very careful of the alignment forced by the dc.b statement.
  121.         LSC aligns each dc.b. I don't know of any other way in LSC to
  122.         generate these Pascal strings needed in the Vantage header, which
  123.         means every time you change the strings, you have to hand-count
  124.         the bytes, change the size bytes, adjust the pad bytes, and worry
  125.         about alignment.
  126.     
  127.     2.) LSC can only generate PC-relative offsets in the dc.w statement.
  128.         Since Vantage wants header-relative offsets for each of the entry
  129.         points, we have to correct the offsets generated by the LSC assembler
  130.         when we Open. Fortunately, the Open offset is the same in either
  131.         method of calculation and Open is always called first, so we can fix
  132.         the other three offsets when we Open
  133.     
  134.     3.) Since we're using a custom header, we have to load A0 ourselves
  135.         on entry to each routine. (Actually, we only need A0 setup so that
  136.         RememberA0() works, and we only need RememberA0 if we need globals.
  137.         Only our Execute routine needs globals (implicitly for the error
  138.         strings), so we really only need the A0 setup and SetUpA4() and
  139.         RestoreA4() stuff in the Execute routine. But I put it all in
  140.         every routine just for consistency's sake.
  141. */
  142.  
  143. void header()
  144. {
  145.  
  146.     asm    {
  147.     
  148.             dc.w    @1        ; Offset to Open routine
  149.             dc.w    @2        ; Offset to Close routine    (almost - see note)
  150.             dc.w    @3        ; Offset to Execute routine    (almost - see note)
  151.             dc.w    @4        ; Offset to Idle routine    (almost - see note)
  152.             dc.w    0x0100    ; First byte is the need_idle_calls boolean (we do)
  153.                             ; Second byte is spare reserved for future use
  154.                             
  155.         ; Next 50 bytes are the menu title (and pad) for this VCMD...
  156.             dc.b    15, 'D', 'e', 'l', 'e', 't', 'e', ' ', 'F', 'i', 'l', 'e', 's', '.', '.', '.'
  157.             dc.b    0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  158.             dc.b    0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  159.             dc.b    0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  160.             dc.b    0, 0, 0, 0
  161.             
  162.         ; The VCMD installer identification string...
  163.             dc.b    13, 'F', 'i', 'l', 'e', 's', ' ', 'D', 'e', 'l', 'e', 't', 'e', 'r'
  164.         
  165.         @1:    lea        header,a0        ; We must load A0 ourselves so RememberA0() works
  166.             addq.w    #2,2(a0)        ; Fix up other three offsets per above note
  167.             addq.w    #4,4(a0)
  168.             addq.w    #6,6(a0)
  169.             jmp        open
  170.         
  171.         @2:    lea        header,a0
  172.             jmp        close
  173.         
  174.         @3:    lea        header,a0
  175.             jmp        execute
  176.         
  177.         @4:    lea        header,a0
  178.             jmp        idle
  179.     }
  180.  
  181. }
  182.  
  183. /**************************************************************/
  184. /* Include LSC's magical A0 and A4 stuff...    */
  185. /* This must be somewhere _after_ the header() function.    */
  186.  
  187. static    __GetA4(void);
  188. void    SetUpA4(void);
  189.  
  190. #include    <SetupA4.h>
  191.  
  192. /****************************************************************/
  193.  
  194. void main()
  195. {
  196.  
  197.     /* We don't use a main()    */
  198. }
  199.  
  200. /****************************************************************/
  201. /* Globals:    */
  202.  
  203. int        sfgresult;        /* result from SFGet dialog (1 = cancel, 2 = do it)    */
  204.  
  205. HFileInfo    ioparms;    /* parameter block for I/O calls    */
  206.  
  207. Handle    flisthdl;        /* list of files to open    */
  208. char    *flist;            /* ptr to same                */
  209.  
  210. Handle    reshdl;            /* result text we send back to Vantage    */
  211. long    ressize;        /* size of same                            */
  212.  
  213. char    *put;            /* ptr to next free char in current list (file list or result text)    */
  214. long    putsize;        /* size of current list                        */
  215.  
  216. bool    toobig;            /* TRUE if too many files    */
  217.  
  218. int        itype;            /* used to GetDItem's    */
  219. Handle    ihdl;
  220. Rect    irect;
  221.  
  222. Str255    dfilename;        /* the wildcard filename specified in the setup dialog    */
  223. long    dtype;            /* the file type in same    */
  224. long    dcreator;        /* the file creator in same    */
  225.  
  226. extern    char    ParmDITLList[], ParmDlogRect[];    /* the setup dialog's DITL and bounds rect
  227.                                                     (in the .asm file)    */
  228.  
  229. bool    error;            /* TRUE if an error has occurred    */
  230.  
  231. bool    needupdate;        /* TRUE if we need to force a Vantage update in our idle routine    */
  232.  
  233. /****************************************************************/
  234. /* Called once when Vantage is opened. Use it to do any necessary
  235.     setup. If you return an error code, then your VCMD resource is
  236.     dumped and won't be called again.    */
  237.  
  238. pascal int open(vantdata, errmsg)
  239.     uchar    *vantdata;
  240.     char    **errmsg;
  241. {
  242.  
  243.     int        result;
  244.  
  245.     RememberA0();
  246.     SetUpA4();
  247.     
  248.     dfilename[0] = 0;        /* initialize our dialog parameter fields    */
  249.     dtype = dcreator = 0;
  250.     
  251.     needupdate = FALSE;        /* don't have to force an update yet    */
  252.     
  253.     RestoreA4();
  254.     
  255.     return    OK;        /* Tell Vantage the result.    */
  256. }
  257.  
  258. /****************************************************************/
  259. /* Called when Vantage is closed. After you're closed, Vantage dumps
  260.     the VCMD resource.    */
  261.  
  262. pascal int close(vantdata, errmsg)
  263.     uchar    *vantdata;
  264.     char    **errmsg;
  265. {
  266.  
  267. /* We don't need any close processing
  268.  
  269.     RememberA0();
  270.     SetUpA4();
  271.  
  272.     do_close_stuff();
  273.     
  274.     RestoreA4();
  275.     
  276. */
  277.  
  278.     return    OK;
  279. }
  280.  
  281. /****************************************************************/
  282. /* The Execute routine is the body of the VCMD. It's called when the
  283.     user selects your VCMD menu item from Vantage's External menu. You
  284.     can do whatever you want when Execute is called, but Vantage assumes
  285.     you're going to operate on the text in the current window, so he
  286.     passes you that text and allows you to return new text to replace it.
  287.     If you don't operate on the text, then you must tell Vantage that by
  288.     returning 'newtext' set to zero. If you do return any replacement text,
  289.     then Vantage will dispose of the newtext handle you return after it
  290.     pastes in the newtext. (But if you return an error code, then Vantage
  291.     assumes that you've disposed of any memory that you allocated.)
  292.  
  293.     The text you're passed is all of the text in the window if nothing is
  294.     selected, otherwise only the selected text is passed. If you return a
  295.     result code of 0, then Vantage replaces all of the passed text with the
  296.     new text you return. If you return a result code of 1, then Vantage will
  297.     use the new text for a standard Paste operation.
  298.  
  299.     There are also two other special result codes:
  300.         result = 2 = set selection in current window to newtext (start)
  301.                         and newlength (end)
  302.         result = 3 = set selection in current window to newtext (start)
  303.                         and newlength (end) and then scroll to that selection
  304.     (Result codes 2 and 3 are only supported in Vantage V2.0 or above.)
  305.     
  306. */
  307.  
  308. pascal int execute(oldtext, oldlength, newtext, newlength, vantdata, winddata, errmsg)
  309.     uchar    *oldtext;
  310.     long    oldlength;    
  311.     Handle    *newtext;
  312.     long    *newlength;
  313.     uchar    *vantdata;
  314.     Handle    winddata;
  315.     char    **errmsg;
  316. {
  317.  
  318.     unsigned int    resourcebase, saverescfile;
  319.     int        i, index, numfiles;
  320.     uchar    *p;
  321.     SFReply    reply;
  322.     Str255    filename;
  323.     long    dirid;
  324.  
  325.     RememberA0();
  326.     SetUpA4();
  327.     
  328.     /* get the base value of Vantage's resources.    */
  329.  
  330.     asm {
  331.         move.l    vantdata,a0
  332.         move.w    0x26(a0),resourcebase
  333.     }
  334.  
  335.     error = FALSE;
  336.     *newtext = *newlength = 0;
  337.     flisthdl = reshdl = toobig = numfiles = ressize = 0;
  338.     
  339.     /* save the current resource file path and make sure we go to the system
  340.         file for Vantage's SFGet dialog resource.    */
  341.         
  342.     saverescfile = CurResFile();
  343.     UseResFile(0);
  344.     
  345.     InitCursor();
  346.  
  347.     if (FSFCBLen == -1) {
  348.         return_errmsg("\pThis VCMD only works with HFS!", errmsg);
  349.     }
  350.     else {
  351.         flisthdl = NewHandle(MAXLIST);    /* get a handle for the list of filenames in the folder    */
  352.         if (flisthdl == 0) {
  353.             return_errmsg("\pOut of memory in Delete Files VCMD!", errmsg);
  354.         }
  355.         else {
  356.             reshdl = NewHandle(MAXLIST);    /* get a handle for the result text we'll return to Vantage    */
  357.             if (reshdl == 0) {
  358.                 return_errmsg("\pOut of memory in Delete Files VCMD!", errmsg);
  359.             }
  360.             else {
  361.                 if (do_param_dialog()) {    /* get delete parameters from user    */
  362.  
  363.                     HLock(flisthdl);    /* prepare to collect matching filenames into our list    */
  364.                     put = *flisthdl;    putsize = 0;
  365.                     
  366.                     /* let them pick a folder using Vantage's custom SFGet dialog    */
  367.  
  368.                     SFPGetFile(0x400040, 0, &SFFileFilter, -1, 0, &SFDlogHook, &reply, (SFGetDlog+resourcebase), 0);
  369.                     
  370.                     if (sfgresult == 1) {
  371.                     
  372.                         /* if they didn't cancel it...    */
  373.     
  374.                         p = (uchar *) &ioparms;        /* clear the I/O parameter block    */
  375.                         for (i = 0; i < sizeof(HFileInfo); i++)
  376.                             *p++ = 0;
  377.     
  378.                         ioparms.ioVRefNum = reply.vRefNum;    /* which volume    */
  379.                         dirid = CurDirStore;                /* which directory    */
  380.                         index = 1;                            /* start with first file in folder    */
  381.     
  382.                         /* collect all the files which match the filters into flist    */
  383.  
  384.                         while (TRUE) {
  385.                             ioparms.ioFDirIndex = index++;
  386.                             ioparms.ioDirID = dirid;
  387.                             ioparms.ioNamePtr = (uchar *) &filename;
  388.                     
  389.                             if (PBGetCatInfo(&ioparms, FALSE) != 0)
  390.                                 break;        /* no more files in folder    */
  391.                                 
  392.                             if (!(ioparms.ioFlAttrib & 0x10)) {        /* ignore folder names    */
  393.                                 if (match_file(&ioparms)) {            /* does file match filters?    */
  394.                                     putbyte(filename[0]);            /* yes - remember its name    */
  395.                                     putstring((char *) &filename);
  396.                                     numfiles++;
  397.                                 }
  398.                             }
  399.                             if (toobig)
  400.                                 break;        /* too many filenames!    */
  401.                         }
  402.                 
  403.                         flist = *flisthdl;    /* reset ptr back to filename list beginning    */
  404.                         HLock(reshdl);        /* prepare to stuff result text into reshdl    */
  405.                         put = *reshdl;
  406.                         putsize = 0;
  407.                 
  408.                         if (numfiles) {
  409.                         
  410.                             /* build a text message detailing the files we delete or not...    */
  411.                             
  412.                             putstring("\p\rDeleting following files...\r");
  413.                             
  414.                             while (numfiles--) {
  415.                             
  416.                                 putbyte(0x09);        /* tab and then filename    */
  417.                                 putstring(flist);
  418.                                 
  419.                                 ioparms.ioFDirIndex = 0;
  420.                                 ioparms.ioDirID = dirid;
  421.                                 ioparms.ioNamePtr = (uchar *) flist;
  422.                                 
  423.                                 if (PBDelete(&ioparms, FALSE) == 0) {
  424.                                     putstring("\p\tOK");
  425.                                 }
  426.                                 else {
  427.                                     putstring("\p\t***--> Error - couldn't delete.");
  428.                                 }
  429.                         
  430.                                 putbyte(0x0d);        /* one file per line */
  431.                                 
  432.                                 flist += (*flist + 1);    /* bump to next file name in list    */
  433.                         
  434.                                 if (toobig)
  435.                                     break;        /* too many filenames!    */
  436.                             }
  437.                             ressize = putsize;
  438.                         }
  439.                         else {
  440.                             return_errmsg("\pNo files match the filters!", errmsg);
  441.                         }
  442.                     }
  443.                 }
  444.             }
  445.         }
  446.     }
  447.     
  448.     if (toobig)
  449.         return_errmsg("\pToo many files - aborted!", errmsg);
  450.  
  451.     UseResFile(saverescfile);
  452.  
  453.     if (ressize) {        /* if we have result text    */
  454.         *newtext = reshdl;        /* then give it to Vantage    */
  455.         *newlength = putsize;
  456.         HUnlock(reshdl);
  457.     }
  458.     else {
  459.         if (reshdl)
  460.             DisposHandle(reshdl);    /* else dump the unused result text handle    */
  461.     }
  462.  
  463.     if (flisthdl)                /* we're done with our filename list now    */
  464.         DisposHandle(flisthdl);
  465.     
  466.     needupdate = TRUE;        /* see comment in idle routine    */
  467.     
  468.     if (error) {
  469.         RestoreA4();
  470.         return ERR;
  471.     }
  472.     else {
  473.         RestoreA4();
  474.         return PASTE_OK;    /* don't replace text - do a normal paste    */
  475.     }
  476. }
  477.  
  478. /****************************************************************/
  479. /* Given a file from the folder, decide if we want to delete it.
  480.     File has to match our wildcard name, our type, and our creator.    */
  481.  
  482. bool match_file(iop)
  483.     HFileInfo    *iop;
  484. {
  485.  
  486.     if (dfilename[0]) {
  487.         if (!match_name((char *) iop->ioNamePtr))
  488.             return FALSE;
  489.     }
  490.     if (dtype) {
  491.         if (iop->ioFlFndrInfo.fdType != dtype)
  492.             return FALSE;
  493.     }
  494.     if (dcreator) {
  495.         if (iop->ioFlFndrInfo.fdCreator != dcreator)
  496.             return FALSE;
  497.     }
  498.     return TRUE;
  499. }
  500.  
  501. /****************************************************************/
  502. /* Given a filename, determine if it matches our wildcard name.
  503.     '*' matches any group of characters.
  504.     '?' matches any single character.
  505.     (Just like MS-DOS or CP/M, pardon my language.)
  506.  
  507. /* Kludge alert!!!    */
  508.  
  509.  
  510. bool match_name(name)
  511.     char    *name;
  512. {
  513.  
  514.     char    pattern[256], query[256];
  515.     char    *p, *q, c;
  516.     
  517.     if (!dfilename[0])
  518.         return FALSE;
  519.     
  520.     PtoCstr((char *) dfilename);
  521.     PtoCstr(name);
  522.     strcpy(pattern, (char *) dfilename);
  523.     strcpy(query, name);
  524.     CtoPstr((char *) dfilename);
  525.     CtoPstr(name);
  526.     for (p = pattern; *p; p++)
  527.         *p = tolower(*p);
  528.     for (q = query; *q; q++)
  529.         *q = tolower(*q);
  530.     
  531.     p = pattern;
  532.     q = query;
  533.     
  534.     while (c = *p++) {
  535.         if (c == '*') {
  536.             if (!(c = *p++))
  537.                 return TRUE;
  538.             while (*q) {
  539.                 if (*q++ == c)
  540.                     break;
  541.             }
  542.             if (!*q) {
  543.                 if ((!*p) && (q[-1] == c))
  544.                     return TRUE;
  545.                 else
  546.                     return FALSE;
  547.             }
  548.         }
  549.         else if (c == '?') {
  550.             q++;
  551.         }
  552.         else {
  553.             if (c != *q++)
  554.                 return FALSE;
  555.         }
  556.         
  557.         if ((!*p) && (!*q))
  558.             return TRUE;
  559.         
  560.         if (!*p)
  561.             return FALSE;
  562.         
  563.         if (!*q) {
  564.             if ((*p == '*') && (!p[1]))
  565.                 return TRUE;
  566.             else
  567.                 return FALSE;
  568.         }    
  569.     }
  570.     if (!*q)
  571.         return TRUE;
  572.     else
  573.         return FALSE;
  574. }
  575.  
  576. /****************************************************************/
  577. /* Get the wildcard filename and the allowable file types and creators
  578.     from the user.    */
  579.  
  580. bool do_param_dialog()
  581. {
  582.  
  583.     int            ditlsize, i, hit;
  584.     char        *p;
  585.     GrafPort    *saveport;
  586.     DialogPtr    dlogptr;
  587.     Handle        ditlhdl;
  588.  
  589.     /* First stuff our DITL list into a handle.    */
  590.     
  591.     ditlsize = (ParmDlogRect - ParmDITLList);
  592.     ditlhdl = NewHandle(ditlsize);
  593.     
  594.     if (ditlhdl == 0)
  595.         return FALSE;
  596.         
  597.     p = *ditlhdl;
  598.     i = 0;
  599.     while (ditlsize--)
  600.         *p++ = ParmDITLList[i++];
  601.  
  602.     /* save the current port, display the dialog, and set it as the current port    */
  603.     
  604.     GetPort(&saveport);
  605.     dlogptr = NewDialog(0, &ParmDlogRect, "", -1, 1, -1, 0, 0, ditlhdl);
  606.     SetPort(dlogptr);
  607.     
  608.     /* default the parameters to whatever they were on last use of the VCMD    */
  609.     
  610.     GetDItem(dlogptr, NAMETEXT, &itype, &ihdl, &irect);
  611.     SetIText(ihdl, &dfilename);
  612.     SelIText(dlogptr, NAMETEXT, 0, 32000);
  613.     Set4TextChars(dlogptr, dtype, TYPETEXT);
  614.     Set4TextChars(dlogptr, dcreator, CREATORTEXT);
  615.  
  616.     /* highlight the OK button    */
  617.     
  618.     GetDItem(dlogptr, OKBUTTON, &itype, &ihdl, &irect);
  619.     PenSize(3, 3);
  620.     InsetRect(&irect, -4, -4);
  621.     FrameRoundRect(&irect, 16, 16);
  622.     PenNormal();
  623.     
  624.     /* handle events in the dialog    */
  625.     
  626.     while (TRUE) {
  627.         ModalDialog(0, &hit);
  628.         switch (hit) {
  629.             case OKBUTTON:
  630.                 GetDItem(dlogptr, NAMETEXT, &itype, &ihdl, &irect);
  631.                 GetIText(ihdl, &dfilename);
  632.                 dtype = Get4TextChars(dlogptr, TYPETEXT);
  633.                 dcreator = Get4TextChars(dlogptr, CREATORTEXT);
  634.                 
  635.                 DisposDialog(dlogptr);
  636.                 SetPort(saveport);
  637.                 
  638.                 /* make sure they specify at least one parameter as a safety net    */
  639.                 
  640.                 if (dfilename[0] | dtype | dcreator)
  641.                     return TRUE;
  642.                 else
  643.                     return FALSE;
  644.  
  645.             case CANCELBUTTON:
  646.                 DisposDialog(dlogptr);
  647.                 SetPort(saveport);
  648.                 return FALSE;
  649.                 
  650.             case NAMETEXT:
  651.             case TYPETEXT:
  652.             case CREATORTEXT:
  653.             default:
  654.                 break;
  655.         }
  656.     }
  657.  
  658. }
  659.  
  660. /****************************************************************/
  661. /* Used to set the file type or creator in the dialog.    */
  662.  
  663. void Set4TextChars(dlogptr, itemval, itemnum)
  664.     DialogPtr    dlogptr;
  665.     long        itemval;
  666.     int            itemnum;
  667. {
  668.  
  669.     Str255    text;
  670.     
  671.     if (!itemval)
  672.         text[0] = 0;
  673.     else {
  674.         text[0] = 4;
  675.         text[1] = (itemval & 0xFF000000L) >> 24;
  676.         text[2] = (itemval & 0x00FF0000L) >> 16;
  677.         text[3] = (itemval & 0x0000FF00L) >> 8;
  678.         text[4] = (itemval & 0x000000FFL);
  679.     }
  680.     GetDItem(dlogptr, itemnum, &itype, &ihdl, &irect);
  681.     SetIText(ihdl, &text);
  682. }
  683.  
  684. /****************************************************************/
  685. /* Used to get the file type or creator from the dialog.    */
  686.  
  687. long Get4TextChars(dlogptr, itemnum)
  688.     DialogPtr dlogptr;
  689.     int     itemnum;
  690. {
  691.  
  692.     int        i;
  693.     Str255    text;
  694.     long    result;
  695.  
  696.     GetDItem(dlogptr, itemnum, &itype, &ihdl, &irect);
  697.     GetIText(ihdl, &text);
  698.     
  699.     if (text[0] < 4)
  700.         return 0;
  701.     else {
  702.         result = 0;
  703.         for (i = 1; i <= 4; i++)
  704.             result = (result << 8) | text[i];
  705.         return result;
  706.     }
  707.  
  708. }
  709.  
  710. /****************************************************************/
  711. /* Our filter proc for the SFGet dialog where we decide if we want
  712.     to display a filename in the filename list.    */
  713.  
  714. pascal bool SFFileFilter(iop)
  715.     HFileInfo    *iop;
  716. {
  717.  
  718.     bool    res;
  719.     
  720.     SetUpA4();
  721.  
  722.     res = match_file(iop);
  723.     
  724.     RestoreA4();
  725.     
  726.     if (res)
  727.         return FALSE;
  728.     else
  729.         return -1;
  730.     
  731. }
  732.  
  733. /****************************************************************/
  734. /* Handles the non-standard buttons in Vantage's SFGet dialog.    */
  735.  
  736. pascal int SFDlogHook(item, dlogptr)
  737.     int            item;
  738.     DialogPtr    dlogptr;
  739. {
  740.  
  741.     int        result;
  742.     
  743.     SetUpA4();
  744.     
  745.     result = item;
  746.     
  747.     if (item == -1) {
  748.         GetDItem(dlogptr, ListFilesButton, &itype, &ihdl, &irect);
  749.         SetCTitle(ihdl, "\pDelete Files");
  750.     }
  751.     else if ((item == ListFilesButton) || (item == OpenButton)) {
  752.         result = OpenButton;
  753.         sfgresult = 1;
  754.     }
  755.     else if (item == CancelButton) {
  756.         sfgresult = 2;
  757.     }
  758.  
  759.     RestoreA4();
  760.     
  761.     return result;
  762.     
  763. }
  764.  
  765. /****************************************************************/
  766. /* Stuff a byte into our current list.    */
  767.  
  768. void putbyte(byt)
  769.     uchar    byt;
  770. {
  771.  
  772.     if (putsize >= MAXLIST) {
  773.         toobig = TRUE;
  774.     }
  775.     else {
  776.         *put++ = byt;
  777.         putsize++;
  778.     }
  779.  
  780. }
  781.  
  782. /****************************************************************/
  783. /* Stuff a string into our current list.    */
  784.     
  785. void putstring(str)
  786.     char    *str;
  787. {
  788.  
  789.     int        length;
  790.     
  791.     length = *str++;
  792.     
  793.     while (length) {
  794.         putbyte(*str++);
  795.         length--;
  796.     }
  797. }
  798.  
  799. /****************************************************************/
  800.  
  801. char tolower(c)
  802.     char    c;
  803. {
  804.     if ((c >= 'A') && (c <= 'Z'))
  805.         c |= 0x20;
  806.  
  807.     return c;
  808. }
  809.     
  810. /****************************************************************/
  811. /* The Idle routine gives you a chance to periodically perform tasks.
  812.     You don't need an Idle routine unless you tell Vantage you want
  813.     idle calls in the boolean byte in the header. */
  814.  
  815. pascal int idle(menu, mitem, vantdata, winddata, errmsg)
  816.     Handle    menu;
  817.     int        mitem;
  818.     uchar    *vantdata;
  819.     Handle    winddata;
  820.     char    **errmsg;
  821. {
  822.  
  823.     uchar    *p;
  824.     EventRecord event;
  825.     
  826.     RememberA0();
  827.     SetUpA4();
  828.     
  829.     /* We need an idle routine just for cosmetic reasons. Since we had two dialogs
  830.         up without going back to Vantage, all of the current Vantage window doesn't
  831.         always get updated after we're done. I'm not sure if this is a Vantage problem
  832.         or a system problem, but I suspect it's something in the system. At any rate,
  833.         if we force a complete update of Vantage's current window here the problem
  834.         is fixed.    */
  835.     
  836.     if (needupdate) {        /* if we've just done a delete    */
  837.     
  838.         if (!EventAvail(updateMask, &event)) {    /* let all normal updates proceed first    */
  839.         
  840.             asm {                            /* then force an update by invalidating Vantage's window    */
  841.                 move.l    winddata,a0
  842.                 move.l    (a0),a0        /* a0 = ptr to Vantage's current window's record    */
  843.                 move.l    (a0),a0        /* a0 = window ptr for same    */
  844.                 lea        16(a0),a0    /* a0 = address of window's portRect    */
  845.                 move.l    a0,p
  846.             }
  847.             InvalRect(p);            /* invalidate window's portRect    */
  848.             
  849.             needupdate = FALSE;    /* only do this once after a delete    */
  850.         }
  851.     }
  852.     
  853.     RestoreA4();
  854.     
  855.     return    OK;
  856. }
  857.  
  858. /****************************************************************/
  859. /* Returns a pointer to an error message to Vantage.    */
  860.  
  861. void return_errmsg(msg, msgptr)
  862.     char    *msg;
  863.     char    **msgptr;
  864. {
  865.  
  866.     *msgptr = msg;
  867.     error = TRUE;
  868. }
  869.  
  870. /****************************************************************/
  871. /* Here's the assembly source file I used to create the DITL list
  872.     for the parameters dialog. (This is in McAssembly format.) You
  873.     can make the DITL list anyway you want to. I just found it
  874.     easier to do it in assembly then in C.
  875.  
  876.  
  877. BUTTONITEM        equ    4
  878. RADIOBUTTONITEM    equ    6
  879. STATICTEXTITEM    equ    8
  880. EDITTEXTITEM    equ    16
  881.  
  882.  
  883.             def    ParmDITLList, ParmDlogRect
  884.             
  885. ParmDITLList
  886.             dc.w    12-1
  887.             
  888. .1            dc.l    0
  889.             dc.w    210, 188, 230, 248
  890.             dc.b    BUTTONITEM
  891.             text    #"OK"
  892.             align
  893.             
  894. .2            dc.l    0
  895.             dc.w    210, 56, 230, 116
  896.             dc.b    BUTTONITEM
  897.             text    #"Cancel"
  898.             align
  899.             
  900. .3            dc.l    0
  901.             dc.w    4, 77, 25, 220
  902.             dc.b    STATICTEXTITEM
  903.             text    #"Delete file filters..."
  904.             align
  905.             
  906. .4            dc.l    0
  907.             dc.w    105, 30, 125, 76
  908.             dc.b    STATICTEXTITEM
  909.             text    #"Name:"
  910.             align
  911.             
  912. .5            dc.l    0
  913.             dc.w    105, 84, 122, 289
  914.             dc.b    EDITTEXTITEM
  915.             text    #""
  916.             align
  917.             
  918. .6            dc.l    0
  919.             dc.w    130, 50, 150, 295
  920.             dc.b    STATICTEXTITEM
  921.             text    #"'*' matches any group of characters."
  922.             align
  923.             
  924. .7            dc.l    0
  925.             dc.w    155, 50, 175, 279
  926.             dc.b    STATICTEXTITEM
  927.             text    #"'?' matches any single character."
  928.             align
  929.             
  930. .8            dc.l    0
  931.             dc.w    180, 30, 200, 72
  932.             dc.b    STATICTEXTITEM
  933.             text    #"Type:"
  934.             align
  935.  
  936. .9            dc.l    0
  937.             dc.w    180, 82, 197, 127
  938.             dc.b    EDITTEXTITEM
  939.             text    #""
  940.             align
  941.             
  942. .10            dc.l    0
  943.             dc.w    180, 166, 200, 226
  944.             dc.b    STATICTEXTITEM
  945.             text    #"Creator:"
  946.             align
  947.  
  948. .11            dc.l    0
  949.             dc.w    180, 235, 197, 280
  950.             dc.b    EDITTEXTITEM
  951.             text    #""
  952.             align
  953.  
  954. .12            dc.l    0
  955.             dc.w    29, 9, 97, 307
  956.             dc.b    STATICTEXTITEM
  957.             dc.b    .12end - .12beg
  958. .12beg        text    "Only files matching all of the specified filters will be deleted. "
  959.             text    "Blank filters are not used in the filtering process, but if all filters "
  960.             text    "are blank then no files will be deleted."
  961. .12end
  962.             align
  963.             
  964. ParmDlogRect
  965.             dc.w    64, 64, 304, 374
  966.  
  967. /****************************************************************/
  968.  
  969.